 package com.hzeport.bgs22emduty.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hzeport.bgs22emduty.config.SystemConfig;
import com.hzeport.bgs22emduty.config.login.UserInfoDetailVO;
import com.hzeport.bgs22emduty.dto.DutydignInfoListDTO;
import com.hzeport.bgs22emduty.dto.DutydignInfoListoneDTO;
import com.hzeport.bgs22emduty.entity.*;
import com.hzeport.bgs22emduty.enums.DTypeEnum;
import com.hzeport.bgs22emduty.enums.DeleteFlagEnum;
import com.hzeport.bgs22emduty.outbound.*;
import com.hzeport.bgs22emduty.outbound.db.DutySignInfoRepositoryImpl;
import com.hzeport.bgs22emduty.service.DutyScheduleInfoService;
import com.hzeport.bgs22emduty.service.DutySignInfoService;
import com.hzeport.bgs22emduty.util.GuavacacheUtils;
import com.hzeport.bgs22emduty.vo.dutydignInfo.DutydignInfoAnswerSaveVO;
import com.hzeport.bgs22emduty.vo.dutydignInfo.DutydignInfoListVO;
import com.hzeport.bgs22emduty.vo.dutydignInfo.DutydignInfoListoneVO;
import com.hzeport.bgs22emduty.vo.dutydignInfo.DutydignInfoSaveVO;
import com.hzeport.bgs22emduty.common.base.BaseResult;
import com.hzeport.bgs22emduty.common.base.BaseServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * ${comments}
 *
 * @author code generator
 * @date 2022-12-02 11:21:59
 */
@Service
@Slf4j
public class DutySignInfoServiceImpl extends BaseServiceImpl<DutySignInfoRepositoryImpl, DutySignInfo> implements DutySignInfoService {

    @Resource
    private DutyScheduleInfoRepository dutyScheduleInfoRepository;
    @Resource
    private BasePersonInfoRepository basePersonInfoRepository;
    @Resource
    private DutySignInfoRepository dutySignInfoRepository;
    @Resource
    private RestTemplate restTemplate;
    @Resource
    private SystemConfig systemConfig;
    @Resource
    private DutyScheduleInfoService dutyScheduleInfoService;
    @Resource
    private ScreenDutyLogRepository screenDutyLogRepository;
    @Resource
    private BaseDeptInfoRepository baseDeptInfoRepository;
    @Resource
    private ScreenShouldKnowAnswerRepository screenShouldKnowAnswerRepository;
    @Resource
    private ParamDutyRepository paramDutyRepository;
    @Resource
    private GuavacacheUtils guavacacheUtils;

    @Override
    public BaseResult<Page<DutydignInfoListVO>> list(DutydignInfoListDTO dutydignInfoListDTO, UserInfoDetailVO userInfo) {
        dutydignInfoListDTO.setCustomCode(userInfo.getCustomscode());
        PageHelper.startPage(dutydignInfoListDTO.getPageNum(),dutydignInfoListDTO.getPageSize());
        List<DutydignInfoListVO> dutydignInfoListoneVOS=dutyScheduleInfoRepository.listForCustom(dutydignInfoListDTO);
        getParentDeptFor(dutydignInfoListoneVOS);
        PageInfo<DutydignInfoListVO> dutydignInfoListoneVOPageInfo=new PageInfo<>(dutydignInfoListoneVOS);
        List<DutydignInfoListVO> listvo=dutydignInfoListoneVOPageInfo.getList();
        //↓↓↓↓↓↓↓添加值班时间段
        listvo.forEach(d->{
            ParamDuty paramDuty=guavacacheUtils.getParamDuty(d.getDutyTimesId());
            if (paramDuty!=null){
                d.setDDay(d.getDDay()+DTypeEnum.TYPE_DAY_TIME.getValueByCode(paramDuty.getDType())+"("+paramDuty.getDStartTime() + "-" + paramDuty.getDEndTime()+")");
            }
        });
        //↑↑↑↑↑↑
        Page<DutydignInfoListVO> dutydignInfoListVOPage = new Page<>();
        dutydignInfoListVOPage.setRecords(listvo);
        dutydignInfoListVOPage.setTotal(dutydignInfoListoneVOPageInfo.getTotal());
        return BaseResult.ok(dutydignInfoListVOPage,"查询成功");
    }
    private void getParentDeptFor(List<DutydignInfoListVO> dutyScheduleInfos) {
        List<BaseDeptInfo> deptInfoList = guavacacheUtils.getDepts();
        Map<String,BaseDeptInfo> deptInfoMap=deptInfoList.stream().collect(Collectors.toMap(BaseDeptInfo::getId, i->i));
        for (DutydignInfoListVO dutyScheduleInfo:dutyScheduleInfos){
            BaseDeptInfo  baseDeptInfo=deptInfoMap.get(dutyScheduleInfo.getDDept());
            if (baseDeptInfo!=null){
                BaseDeptInfo parent=deptInfoMap.get(baseDeptInfo.getParentid());
                if (parent!=null&&!systemConfig.getZsCustomName().equals(parent.getDeptName())
                        &&!StringUtils.isEmpty(parent.getDeptName())&&!parent.getDeptName().contains("海关")){
                    dutyScheduleInfo.setDDeptname(dutyScheduleInfo.getDDeptname()+"("+parent.getDeptName()+")");
                }
            }
        }
    }
    @Override
    public BaseResult<Page<DutydignInfoListoneVO>> listone(DutydignInfoListoneDTO dutydignInfoListoneDTO, UserInfoDetailVO userInfo) {
        dutydignInfoListoneDTO.setUserCode(userInfo.getUserId());
        PageHelper.startPage(dutydignInfoListoneDTO.getPageNum(),dutydignInfoListoneDTO.getPageSize());
        List<DutydignInfoListoneVO> dutydignInfoListoneVOS=dutyScheduleInfoRepository.listone(dutydignInfoListoneDTO);
        PageInfo<DutydignInfoListoneVO> dutydignInfoListoneVOPageInfo=new PageInfo<>(dutydignInfoListoneVOS);
        List<DutydignInfoListoneVO> listvo=dutydignInfoListoneVOPageInfo.getList();
        Page<DutydignInfoListoneVO> dutydignInfoListVOPage = new Page<>();
        dutydignInfoListVOPage.setRecords(listvo);
        dutydignInfoListVOPage.setTotal(dutydignInfoListoneVOPageInfo.getTotal());
        return BaseResult.ok(dutydignInfoListVOPage,"查询成功");
    }

    @Override
    public BaseResult saveData(DutydignInfoSaveVO dutydignInfoSaveVO) throws Exception {
        List<DutyScheduleInfo>  dutyScheduleInfos=dutyScheduleInfoRepository.list(new LambdaQueryWrapper<DutyScheduleInfo>()
                .le(DutyScheduleInfo::getDDay,LocalDate.now())
                .ge(DutyScheduleInfo::getDDay,LocalDate.now().minusDays(2L))
                .in(DutyScheduleInfo::getDUserjob,"科员","科领导","处领导")
                .eq(DutyScheduleInfo::getDUserno,dutydignInfoSaveVO.getPersonCode())
                .orderByDesc(DutyScheduleInfo::getDStartDateTime));
        LocalDateTime now=LocalDateTime.now();
        if (CollectionUtils.isEmpty(dutyScheduleInfos)){
            throw new Exception("工号为"+dutydignInfoSaveVO.getPersonCode()+"的签到/签退人员非值班人员");
        }

        if ("1".equals(dutydignInfoSaveVO.getSignType())&&!CollectionUtils.isEmpty(dutyScheduleInfos)) {
            DutySignInfo dutySignInfo = new DutySignInfo();
            DutyScheduleInfo targetScheduleInfo=getSignInTaragetScheduleInfo(dutyScheduleInfos,now);
            DutySignInfo info = dutySignInfoRepository.getOne(new LambdaQueryWrapper<DutySignInfo>()
                    .eq(DutySignInfo::getDId, targetScheduleInfo.getId()));
            BeanUtils.copyProperties(info, dutySignInfo);
            info.setDSigninType("1");
            if (info.getDSigninTime()==null) {
                info.setDSigninTime(LocalDateTime.now());
            }
            dutySignInfoRepository.updateById(info);
            ScreenDutyLog screenDutyLog = new ScreenDutyLog();
            screenDutyLog.setCustomId(targetScheduleInfo.getCustomId());
            screenDutyLog.setCustomName(targetScheduleInfo.getCustomName());
            ParamDuty paramDuty=guavacacheUtils.getParamDuty(targetScheduleInfo.getDutyTimesId());
            String dutyTypeString=createTypeString(paramDuty);
            String title=DateTimeFormatter.ofPattern("yyyy年MM月dd日").format(targetScheduleInfo.getDDay())
                    +dutyTypeString+"值班情况";
            if (screenDutyLogRepository.count(new LambdaQueryWrapper<ScreenDutyLog>()
            .eq(ScreenDutyLog::getTitle,title)
            .eq(ScreenDutyLog::getCustomId,targetScheduleInfo.getCustomId()))==0) {
                screenDutyLog.setTitle(title);
                screenDutyLog.setCreatePerson(dutydignInfoSaveVO.getPersonCode());
                screenDutyLog.setCreateTime(LocalDateTime.now());
                screenDutyLog.setCreateBy(targetScheduleInfo.getDUserno());
                screenDutyLog.setDistributeCount(0);
                screenDutyLog.setFileCount(0);
                screenDutyLog.setMessageCount(0);
                screenDutyLog.setPhoneCount(0);
                screenDutyLog.setRid(targetScheduleInfo.getId());
                screenDutyLogRepository.save(screenDutyLog);
            }
            return BaseResult.ok("签到成功");
        }
        //进行加班申报
        if ("2".equals(dutydignInfoSaveVO.getSignType())&&!CollectionUtils.isEmpty(dutyScheduleInfos)){
            DutyScheduleInfo targetScheduleInfo=getSignOutTaragetScheduleInfo(dutyScheduleInfos,now);
            DutySignInfo info = dutySignInfoRepository.getOne(new LambdaQueryWrapper<DutySignInfo>()
                    .eq(DutySignInfo::getDId,targetScheduleInfo.getId()));
            if (!"1".equals(info.getDSigninType())){
                throw new Exception("未签到的人员不能签退！");
            }
            if (screenDutyLogRepository.count(new LambdaQueryWrapper<ScreenDutyLog>()
                    .eq(ScreenDutyLog::getRid,targetScheduleInfo.getId())
                    .isNotNull(ScreenDutyLog::getChangeFlag)
                    )==0){
                throw new Exception("签退前需填写日志！");
            }
            ParamDuty paramDuty=guavacacheUtils.getParamDuty(targetScheduleInfo.getDutyTimesId());
            boolean flag = "1".equals(targetScheduleInfo.getSType()) &&
                    ("2".equals(paramDuty.getDType()) ||"１".equals(paramDuty.getDType())|| "６".equals(paramDuty.getDType()) )
                    &&"2".equals(dutydignInfoSaveVO.getHandoverType());
            if(flag){
                throw new Exception("当日班次交接有误,请重新选择！");
            }
            boolean flag1 = !"1".equals(targetScheduleInfo.getSType()) &&
                    (!"2".equals(paramDuty.getDType()) ||!"1".equals(paramDuty.getDType())|| !"6".equals(paramDuty.getDType()) )
                    &&"1".equals(dutydignInfoSaveVO.getHandoverType());
            if(flag1){
                throw new Exception("当日班次交接有误,请重新选择！");
            }
            info.setDSignoutType("1");
            info.setDSignoutTime(LocalDateTime.now());
            dutySignInfoRepository.updateById(info);
            if (!"1".equals(info.getIsHrSend())) {
                dutyScheduleInfoService.doApplyRetry(dutyScheduleInfos.get(0), info);
            }
             return BaseResult.ok("签退成功");
        }
        return BaseResult.ok("保存成功");
    }

    @Override
    public DutyScheduleInfo getSignOutTaragetScheduleInfo(List<DutyScheduleInfo> dutyScheduleInfos,LocalDateTime now) {
        for (int i=0;i<dutyScheduleInfos.size();i++){
            DutySignInfo info = dutySignInfoRepository.getOne(new LambdaQueryWrapper<DutySignInfo>()
                    .eq(DutySignInfo::getDId,dutyScheduleInfos.get(i).getId()));
            if ("1".equals(info.getDSigninType())){
                return dutyScheduleInfos.get(i);
            }
        }
        return dutyScheduleInfos.get(0);
    }

    @Override
    public DutyScheduleInfo getSignInTaragetScheduleInfo(List<DutyScheduleInfo> dutyScheduleInfos, LocalDateTime now) {
        for (DutyScheduleInfo dutyScheduleInfo:dutyScheduleInfos){
            ParamDuty paramDuty=guavacacheUtils.getParamDuty(dutyScheduleInfo.getDutyTimesId());
            if (paramDuty!=null){
                LocalTime startTime=paramDuty.getDStartTime();
                LocalTime endTime=paramDuty.getDEndTime();
                LocalDateTime startDateTime;
                LocalDateTime endDateTime;
                startDateTime=dutyScheduleInfo.getDDay().atTime(startTime).minusMinutes(systemConfig.getSignDelayMinutes());
                if (now.compareTo(startDateTime)>0){
                    return dutyScheduleInfo;
                }
            }
        }
        return dutyScheduleInfos.get(0);
    }

    private String createTypeString(ParamDuty paramDuty) {
        if (paramDuty==null){
            return "";
        }
        if (paramDuty.getDType()==null){
            return "";
        }
        switch (paramDuty.getDType()){
            case "1":
                return "上午";
            case "2":
                return "下午";
            case "3":
                return "夜间";
            case "4":
                return "全天";
            case "5":
                return "其他时段";
            case "6":
                return "白天";
            default:
                return "";
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult answer(DutydignInfoAnswerSaveVO dutydignInfoAnswerSaveVO) throws Exception {
        List<BasePersonInfo> basePersonInfo=basePersonInfoRepository.list(new LambdaQueryWrapper<BasePersonInfo>()
        .eq(BasePersonInfo::getUserno,dutydignInfoAnswerSaveVO.getPersonCode()));
        if (basePersonInfo==null){
            throw new Exception("没有匹配该工号的人员"+dutydignInfoAnswerSaveVO.getPersonCode());
        }
        BasePersonInfo tempBasePerson=basePersonInfo.stream().filter(i->"0".equals(i.getSideLine()))
                .findAny().orElse(null);
        if (tempBasePerson==null){
            tempBasePerson=basePersonInfo.get(0);
        }
        BaseDeptInfo baseDeptInfo=baseDeptInfoRepository.getById(tempBasePerson.getDeptId());
        if (basePersonInfo==null){
            throw new Exception("没有匹配该工号的部门"+dutydignInfoAnswerSaveVO.getPersonCode());
        }
        if (!CollectionUtils.isEmpty(dutydignInfoAnswerSaveVO.getAnswers())){
            List<ScreenShouldKnowAnswer> screenShouldKnowAnswers=dutydignInfoAnswerSaveVO.getAnswers()
                    .stream().map(i->{
                        ScreenShouldKnowAnswer screenShouldKnowAnswer=new ScreenShouldKnowAnswer();
                        BeanUtils.copyProperties(i,screenShouldKnowAnswer);
                        screenShouldKnowAnswer.setCustomId(baseDeptInfo.getId());
                        screenShouldKnowAnswer.setCustomName(baseDeptInfo.getDeptName());
                        screenShouldKnowAnswer.setUserName(basePersonInfo.get(0).getUsername());
                        screenShouldKnowAnswer.setDelFlag(DeleteFlagEnum.NOT_DELETE.getValue());
                        screenShouldKnowAnswer.setUserNo(dutydignInfoAnswerSaveVO.getPersonCode());
                        return screenShouldKnowAnswer;
                    }).collect(Collectors.toList());
            screenShouldKnowAnswerRepository.saveBatch(screenShouldKnowAnswers);
        }
        DutydignInfoSaveVO dutydignInfoSaveVO=new DutydignInfoSaveVO();
        dutydignInfoSaveVO.setSignType("1");
        dutydignInfoSaveVO.setPersonCode(dutydignInfoAnswerSaveVO.getPersonCode());
        return saveData(dutydignInfoSaveVO);
    }


    /**
     * applyType	String
     * applyUser	String
     * applyName	String
     * dept	String
     * deptName	String
     * duty	String
     * dutyName	String
     * reason	String
     * applyDate	datetime
     * overTimeList	String
     * @param dutyScheduleInfo
     * @param info
     *
     * {
     *   "ApplyType": "1",
     *   "ApplyUser": "2960430",
     *   "ApplyName": "姚瑛",
     *   "Dept": "89cacb2e-8c20-4102-818b-70de4888469f",
     *   "DeptName": "保税监管科",
     *   "Duty": "string",
     *   "DutyName": "主任科员",
     *   "Reason": "1",
     *   "ApplyDate": "2022-11-12 17:30",
     *   "OverTimeList": [
     *     {
     *       "BeginDate": "2022-11-12 08:30",
     *       "EndDate": "2022-11-12 17:30"
     *     }
     *   ]
     * }
     */


//    @Override
//    public BaseResult savedutysheetData(DutydignInfoSaveVO dutydignInfoSaveVO) {
//        DutyScheduleInfo  dutyScheduleInfos=dutyScheduleInfoRepository.getOne(new LambdaQueryWrapper<DutyScheduleInfo>()
//                .eq(DutyScheduleInfo::getDDay,LocalDate.now()).eq(DutyScheduleInfo::getDUserno,dutydignInfoSaveVO.getPersonCode()));
//        //调用token接口
//        String token=getToken();
//        JSONObject jsonObject=JSONObject.parseObject(dutyScheduleInfos);
//        log.info("");
//        HttpHeaders httpHeaders=new HttpHeaders();
//        httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
//        httpHeaders.add("Accept", MediaType.APPLICATION_JSON.toString());
//        httpHeaders.add("enterpriseName", URLEncoder.encode(planHead.getPublishCompanyName()));
//        httpHeaders.add("enterpriseSccd", planHead.getCoNo());
//        HttpEntity httpEntity=new HttpEntity(jsonObject,httpHeaders);
//        ResponseEntity<JSONObject> responseEntity=bayonetRestTemplate.postForEntity(BAYOENT_BASEURL+BAYOENT_APPLYURL+"?id_token="+token
//                ,httpEntity,JSONObject.class);
//        log.info(responseEntity+"");
//        JSONObject result=responseEntity.getBody().getJSONObject("dataInfo").getJSONObject("data");
//        BayonetApplyResultDTO bayonetApplyResultDTO= JSONObject.parseObject(result.toJSONString(),BayonetApplyResultDTO.class);
//        return null;
//    }


}
